<?php
/**
 * Created by PhpStorm.
 * User: root
 * Date: 11/14/18
 * Time: 9:50 AM
 */

namespace caroltc\jenkinsapp\library;

use caroltc\jenkinsapp\util\Helper;
use caroltc\jenkinsapp\util\Http;

class DingtalkSDK
{
    /**
     * 获取企业授权的凭证
     * @see https://open-doc.dingtalk.com/microapp/isv/xocbve
     * @param $corpid
     * @return string|bool
     * @throws \Exception
     */
    public static function getCorpAccessToken($corpid)
    {
        $result = static::requestDingtalkServer('/service/get_corp_token', ['auth_corpid' => $corpid], static::getCorpAuthParams());
        if (isset($result['access_token'])) {
            return $result['access_token'];
        }
        throw new \Exception('access_token获取失败，未授权企业');
    }

    /**
     * 获取授权的凭证
     * @see https://open-doc.dingtalk.com/microapp/isv/xocbve
     * @return string|bool
     * @throws \Exception
     */
    public static function getAccessToken($corpid)
    {
        $result = static::queryDingtalkServer('/gettoken', ['appkey' => Facade::config('appkey'), 'appsecret' => Facade::config('appsecret')]);
        if (isset($result['access_token'])) {
            return $result['access_token'];
        }
        throw new \Exception('access_token获取失败，未授权企业');
    }

    /**
     * 获取企业基本信息
     * @see https://open-doc.dingtalk.com/microapp/isv/xocbve
     * @param $corpid
     * @return array|mixed
     */
    public static function getCorpAuthInfo($corpid)
    {
        return static::requestDingtalkServer('/service/get_auth_info', ['auth_corpid' => $corpid], static::getCorpAuthParams());
    }

    /**
     * 服务端通过免登码获取userid
     * @see https://open-doc.dingtalk.com/microapp/isv/tggei1
     * @param $corpid
     * @param $auth_code
     * @return array|mixed
     * @throws \Exception
     */
    public static function getUserInfoByAuthCode($corpid, $auth_code)
    {
        $access_token = static::getAccessToken($corpid);
        $result = static::queryDingtalkServer('/user/getuserinfo', ['access_token' => $access_token, 'code' => $auth_code]);
        if (empty($result) || !isset($result['userid'])) {
            throw new \Exception('用户id拉取失败');
        }
        return static::getUserInfoByUserId($corpid, $result['userid'], $access_token);
    }

    /**
     * 获取用户详情
     * @see https://open-doc.dingtalk.com/microapp/serverapi2/ege851#%E8%8E%B7%E5%8F%96%E7%94%A8%E6%88%B7%E8%AF%A6%E6%83%85
     * @param $corpid
     * @param $user_id
     * @param string $access_token
     * @return array|mixed
     * @throws \Exception
     */
    public static function getUserInfoByUserId($corpid, $user_id, $access_token = '')
    {
        $access_token = empty($access_token) ? static::getAccessToken($corpid) : $access_token;
        $result = static::queryDingtalkServer('/user/get', ['access_token' => $access_token, 'userid' => $user_id, 'lang' => 'zh_CN']);
        if (!empty($result)) {
            return $result;
        }
        throw new \Exception('用户信息拉取失败');
    }

    /**
     * 获取公司认证参数(部分接口通用)
     * @return array
     */
    private static function getCorpAuthParams()
    {
        $time_stamp = Helper::getMillisecond();
        $suite_ticket = static::getSuitTicket();
        return  [
            'accessKey' => Facade::config('suite_key'),
            'timestamp' => $time_stamp,
            'suiteTicket' => $suite_ticket,
            'signature' => static::getSignature($time_stamp, $suite_ticket)
        ];
    }

    /**
     * 请求钉钉服务器(POST)
     * @param $url
     * @param $data
     * @param array $url_params
     * @return array|mixed
     */
    private static function requestDingtalkServer($url, $data, $url_params = [])
    {
        $result = Http::postJson(Facade::config('oapi_host') . $url.'?'.http_build_query($url_params), $data);
        return static::getResult($result);
    }

    /**
     * 查询钉钉服务器(GET)
     * @param $url
     * @param array $url_params
     * @return array|mixed
     */
    private static function queryDingtalkServer($url, $url_params = [])
    {
        $result = Http::get(Facade::config('oapi_host') . $url, $url_params);
        return static::getResult($result);
    }

    /**
     * 得到请求结果(转换成array)
     * @param $result
     * @return array|mixed
     */
    private static function getResult($result)
    {
        return !empty($result) ? json_decode($result, true) : [];
    }

    /**
     * 获取suitTicket,用于和钉钉服务器交互
     * @return string
     */
    private static function getSuitTicket()
    {
        return (new DbHandler())->getSuitTicket();
    }

    /**
     * 构造签名
     * @param $time_stamp
     * @param $suite_ticket
     * @return string
     */
    private static function getSignature($time_stamp, $suite_ticket)
    {
        // 把timestamp+"\n"+suiteTicket当做签名字符串，suiteSecret做为签名秘钥，使用HmacSHA256算法计算签名，然后进行Base64 encode获取最后结果。然后把签名参数再进行urlconde，加到请求url后面
        $msg = $time_stamp."\n".$suite_ticket;
        return base64_encode(hash_hmac('sha256', $msg, Facade::config('suite_secret'), true));
    }
}